function Animal(firstName, lastName)
{
	Animal.$baseConstructor.call(this);

	this.firstName = firstName;
	this.lastName = lastName;
}
p = Animal.extend(AjaxStack.Class, { type: 'Animal' });
p.hello = function(text)
{
	return "hellooo: " + text;
}
Animal.prototype.getFullName = function()
{
	return this.firstName + " " + this.lastName;
}

function Mouse(firstName, lastName)
{
	Cat.$baseConstructor.call(this, firstName, lastName);
}
Mouse.extend(Animal, { type: 'Rodent' }, 
	function(prototype) 
	{
		prototype.getFullName = function() { return "squeak: " + Cat.$base.getFullName.call(this); }
		prototype.constructor.talk = function() { return "squeak"; }
	}
);

function Cat(catType, firstName, lastName)
{
	Cat.$baseConstructor.call(this, firstName, lastName);

	this.catType = catType;
}
Cat.extend(Animal, { type: 'Cat' }, {
	hello: function(text)
	{
		return "meaoow: " + text;
	},
	getFullName: function()
	{
		return this.catType + ": " + Cat.$base.getFullName.call(this);
	}
});

YAHOO.namespace("ajaxstack");
YAHOO.ajaxstack.ClassTests = new YAHOO.tool.TestCase({

	name: "Inheritance Tests",

	//--------------------------------------------- 
	// Setup and tear down 
	//---------------------------------------------

	setUp: function()
	{
		this.animal = new Animal("Mr", "Animale");
		this.mouse = new Mouse("Mickey", "Mouse");
		this.cat = new Cat("ginger", "Kitty", "Kat");
	},

	tearDown: function()
	{
		delete this.animal;
		delete this.mouse;
		delete this.cat;
	},

	//--------------------------------------------- 
	// Tests 
	//---------------------------------------------

	testStaticTypes: function()
	{
		Assert.areEqual("Animal", Animal.getType());
		Assert.areEqual("Rodent", Mouse.getType(), "Should be different from function name");
		Assert.areEqual("Cat", Cat.getType());
		Assert.areEqual("squeak", Mouse.talk());
	},

	testAnimalMethods: function()
	{
		Assert.areEqual("hellooo: 1", this.animal.hello(1));
		Assert.areEqual("hellooo: 1", this.mouse.hello(1), "Should be the same as Animal");
		Assert.areEqual("meaoow: 1", this.cat.hello(1), "Should be different from Animal");
	},

	testInstanceTypes: function()
	{
		Assert.areEqual(Animal.getType(), this.animal.getType());
		Assert.areEqual(Mouse.getType(), this.mouse.getType());
		Assert.areEqual(Cat.getType(), this.cat.getType());

		ArrayAssert.itemsAreEqual(["AjaxStack.Class"], this.animal.getBaseTypes());
		ArrayAssert.itemsAreEqual(["Animal", "AjaxStack.Class"], this.mouse.getBaseTypes());
		ArrayAssert.itemsAreEqual(["Animal", "AjaxStack.Class"], this.cat.getBaseTypes());

		ArrayAssert.itemsAreEqual(["Animal", "AjaxStack.Class"], this.animal.getBaseTypesAndSelf());
		ArrayAssert.itemsAreEqual(["Rodent", "Animal", "AjaxStack.Class"], this.mouse.getBaseTypesAndSelf());
		ArrayAssert.itemsAreEqual(["Cat", "Animal", "AjaxStack.Class"], this.cat.getBaseTypesAndSelf());

		Assert.areNotEqual(Animal.getType(), this.cat.getType());
		Assert.areNotEqual(Mouse.getType(), this.cat.getType());
		Assert.areNotEqual(Mouse.getType(), this.animal.getType());
	},

	testGetFullName: function()
	{
		Assert.areEqual("Mr Animale", this.animal.getFullName());
		Assert.areEqual("ginger: Kitty Kat", this.cat.getFullName());
		Assert.areEqual("squeak: Mickey Mouse", this.mouse.getFullName());
	},

	testTypeCreation: function()
	{
		var DynamicCat = Class.getConstructor(Cat.getType());
		var dynamicCat = new DynamicCat("tab", "fat", "cat");
		var createNewCat = Class.create(Cat.getType(), ["tab", "fat", "cat"]);

		var cats = [dynamicCat, createNewCat];
		for (var i in cats)
		{
			var cat = cats[i];
			Assert.areEqual("tab: fat cat", cat.getFullName());
			Assert.areEqual(Cat.getType(), cat.getType());
			Assert.areEqual(Cat.getType(), cat.constructor.getType());
			ArrayAssert.itemsAreEqual(["Animal", "AjaxStack.Class"], cat.getBaseTypes());
			ArrayAssert.itemsAreEqual(["Cat", "Animal", "AjaxStack.Class"], cat.getBaseTypesAndSelf());
		}
	}

});

